using Microsoft.Extensions.Logging;
using SeataNet.Core.Common;
using SeataNet.Core.Context;
using SeataNet.Core.Exceptions;
using SeataNet.Core.Protocol;
using SeataNet.Core.Database;
using System.Collections.Concurrent;
using System.Data.Common;
using System.Reflection;
using System.Text.Json;

namespace SeataNet.Core.AT
{
    /// <summary>
    /// AT模式数据源代理
    ///
    /// 职责：
    /// 1. 创建并管理AT代理连接（AtConnectionProxy）
    /// 2. 注册和注销数据库连接
    /// 3. 注册分支事务到TC
    /// 4. 上报分支事务状态
    /// 5. 执行回滚操作（查询undo_log并执行反向SQL）
    /// 6. 管理多种数据库提供程序（SQL Server、MySQL、PostgreSQL、SQLite）
    ///
    /// 工作原理：
    /// ```
    /// 应用层
    ///    ↓
    /// AtDataSourceProxy (数据源代理层)
    ///    ↓
    /// AtConnectionProxy (连接代理层)
    ///    ↓
    /// DbConnection (真实数据库连接)
    /// ```
    ///
    /// 连接创建流程：
    /// 1. 应用调用CreateConnection()
    /// 2. 根据providerName获取DbProviderFactory
    /// 3. 创建目标DbConnection
    /// 4. 包装为AtConnectionProxy
    /// 5. 注册到连接池（_connections）
    /// 6. 返回代理连接
    ///
    /// 分支注册流程：
    /// 1. AtConnectionProxy提交本地事务前调用RegisterBranch
    /// 2. 发送BranchRegisterRequest到TC
    /// 3. TC分配branchId并注册全局锁
    /// 4. 返回branchId
    ///
    /// 回滚流程：
    /// 1. TC发送BranchRollbackRequest
    /// 2. AtDataSourceProxy.Undo()被调用
    /// 3. 查询undo_log表（QueryUndoLogs）
    /// 4. 按相反顺序执行回滚（ExecuteUndo）
    /// 5. 删除undo_log（DeleteUndoLogs）
    /// 6. 上报回滚结果给TC
    ///
    /// 数据库提供程序支持：
    /// - SQL Server：Microsoft.Data.SqlClient（推荐）/ System.Data.SqlClient（兼容）
    /// - MySQL：MySql.Data.MySqlClient
    /// - PostgreSQL：Npgsql
    /// - SQLite：Microsoft.Data.Sqlite
    ///
    /// 线程安全：
    /// - 使用ConcurrentDictionary管理连接池（_connections）
    /// - 连接注册和注销操作是线程安全的
    /// - 每个连接的操作由AtConnectionProxy负责线程安全
    ///
    /// 使用示例：
    /// ```csharp
    /// // 创建数据源代理
    /// var dataSource = new AtDataSourceProxy(
    ///     transactionManager,
    ///     logger,
    ///     loggerFactory,
    ///     connectionString: "Server=...;Database=...",
    ///     providerName: "Microsoft.Data.SqlClient",
    ///     dialect: new SqlServerDialect(),
    ///     tableMetaCache: tableMetaCache
    /// );
    ///
    /// // 创建连接
    /// using (var connection = dataSource.CreateConnection())
    /// {
    ///     await connection.OpenAsync();
    ///
    ///     // 执行业务SQL
    ///     using (var command = connection.CreateCommand())
    ///     {
    ///         command.CommandText = "UPDATE account SET balance = balance - 100 WHERE id = 1";
    ///         await command.ExecuteNonQueryAsync();
    ///     }
    ///
    ///     // 提交本地事务（自动注册分支事务）
    ///     await connection.CommitAsync();
    /// }
    /// ```
    ///
    /// 注意事项：
    /// - 必须在全局事务上下文（RootContext.XID不为空）中使用
    /// - 连接使用完毕后需要正确关闭和释放
    /// - 支持的数据库提供程序需要在运行时可用（NuGet包已安装）
    /// - 回滚操作需要undo_log表存在
    /// - 连接池（_connections）用于跟踪活跃连接，关闭时自动注销
    /// </summary>
    public class AtDataSourceProxy : IAtDataSourceProxy
    {
        private readonly IAtTransactionManager _transactionManager;
        private readonly ILogger<AtDataSourceProxy> _logger;
        private readonly ILoggerFactory _loggerFactory;
        private readonly string _connectionString;
        private readonly string _providerName;
        private readonly Dictionary<string, DbProviderFactory> _providerFactories;
        private readonly ConcurrentDictionary<string, AtConnectionProxy> _connections;
        private readonly IDatabaseDialect _dialect;
        private readonly ITableMetaCache _tableMetaCache;

        /// <summary>
        /// 构造函数
        ///
        /// 初始化AT模式数据源代理，注册所有支持的数据库提供程序。
        ///
        /// 执行流程：
        /// 1. 保存依赖注入的服务：
        ///    - _transactionManager：AT事务管理器，用于注册分支、上报状态
        ///    - _logger：日志记录器
        ///    - _loggerFactory：日志工厂，用于创建子组件的logger
        /// 2. 保存数据库配置：
        ///    - _connectionString：数据库连接字符串
        ///    - _providerName：数据库提供程序名称（默认SQL Server）
        ///    - _dialect：数据库方言（用于生成特定数据库的SQL）
        ///    - _tableMetaCache：表元数据缓存（用于获取表结构）
        /// 3. 初始化内部集合：
        ///    - _providerFactories：数据库提供程序工厂字典
        ///    - _connections：连接池，使用ConcurrentDictionary保证线程安全
        /// 4. 调用RegisterProviderFactories()注册所有支持的数据库提供程序
        ///
        /// 数据库提供程序默认值说明：
        /// - providerName = "Microsoft.Data.SqlClient"：默认使用SQL Server
        /// - 支持的提供程序：
        ///   - Microsoft.Data.SqlClient（SQL Server 2012+，推荐）
        ///   - System.Data.SqlClient（SQL Server旧版本，兼容）
        ///   - MySql.Data.MySqlClient（MySQL 5.6+）
        ///   - Npgsql（PostgreSQL 9.5+）
        ///   - Microsoft.Data.Sqlite（SQLite 3+）
        ///
        /// 注意事项：
        /// - connectionString必须是有效的数据库连接字符串
        /// - providerName必须与已注册的提供程序匹配
        /// - dialect为null时使用默认方言（通常基于providerName推断）
        /// - tableMetaCache为null时不使用缓存（每次查询元数据）
        /// - RegisterProviderFactories()会尝试注册所有提供程序，失败的会记录警告
        /// </summary>
        /// <param name="transactionManager">AT事务管理器，用于分支注册和状态上报</param>
        /// <param name="logger">日志记录器</param>
        /// <param name="loggerFactory">日志工厂，用于创建子组件的logger</param>
        /// <param name="connectionString">数据库连接字符串</param>
        /// <param name="providerName">数据库提供程序名称，默认为SQL Server</param>
        /// <param name="dialect">数据库方言，用于生成特定数据库的SQL，可选</param>
        /// <param name="tableMetaCache">表元数据缓存，用于获取表结构，可选</param>
        public AtDataSourceProxy(
            IAtTransactionManager transactionManager,
            ILogger<AtDataSourceProxy> logger,
            ILoggerFactory loggerFactory,
            string connectionString,
            string providerName = "Microsoft.Data.SqlClient",
            IDatabaseDialect dialect = null,
            ITableMetaCache tableMetaCache = null)
        {
            _transactionManager = transactionManager;
            _logger = logger;
            _loggerFactory = loggerFactory;
            _connectionString = connectionString;
            _providerName = providerName;
            _providerFactories = new Dictionary<string, DbProviderFactory>();
            _connections = new ConcurrentDictionary<string, AtConnectionProxy>();
            _dialect = dialect;
            _tableMetaCache = tableMetaCache;

            // 注册数据库提供程序
            RegisterProviderFactories();
        }

        /// <summary>
        /// 创建AT代理连接
        ///
        /// 创建一个AtConnectionProxy对象，包装底层的数据库连接。
        ///
        /// 执行流程：
        /// 1. 记录调试日志，包含提供程序名称
        /// 2. 调用GetProviderFactory()获取数据库提供程序工厂：
        ///    - 从_providerFactories字典中查找
        ///    - 如果找不到，抛出NotSupportedException
        /// 3. 使用factory.CreateConnection()创建底层DbConnection对象
        /// 4. 设置connectionString到目标连接
        /// 5. 生成唯一的连接ID（GUID）
        /// 6. 创建AtConnectionProxy代理对象：
        ///    - 传入this（数据源代理）
        ///    - 传入_transactionManager（事务管理器）
        ///    - 传入logger（连接专用logger）
        ///    - 传入_loggerFactory（用于创建子组件logger）
        ///    - 传入targetConnection（底层连接）
        ///    - 传入_dialect（数据库方言）
        ///    - 传入_tableMetaCache（表元数据缓存）
        /// 7. 将代理连接注册到连接池（_connections）
        /// 8. 返回代理连接
        ///
        /// 代理连接的职责：
        /// - 捕获业务SQL并生成undo_log
        /// - 自动注册分支事务
        /// - 管理本地事务和全局锁
        /// - 提交时写入undo_log和注册全局锁
        ///
        /// 调用时机：
        /// - 应用需要执行数据库操作时
        /// - 通常在全局事务上下文中使用
        /// - 使用using语句确保连接正确释放
        ///
        /// 使用示例：
        /// ```csharp
        /// using (var connection = dataSource.CreateConnection())
        /// {
        ///     await connection.OpenAsync();
        ///
        ///     using (var command = connection.CreateCommand())
        ///     {
        ///         command.CommandText = "UPDATE account SET balance = balance - 100 WHERE id = 1";
        ///         await command.ExecuteNonQueryAsync();
        ///     }
        ///
        ///     await connection.CommitAsync();
        /// }
        /// ```
        ///
        /// 注意事项：
        /// - 返回的DbConnection实际类型是AtConnectionProxy
        /// - 连接使用完毕后必须Close或Dispose
        /// - 连接Close时会自动从连接池中注销
        /// - 如果providerName不支持，会抛出NotSupportedException
        /// - 连接创建成功不代表连接已打开，需要调用OpenAsync()
        /// </summary>
        /// <returns>AT代理连接对象（AtConnectionProxy）</returns>
        /// <exception cref="NotSupportedException">不支持的数据库提供程序时抛出</exception>
        public DbConnection CreateConnection()
        {
            _logger.LogDebug($"创建AT代理连接: Provider={_providerName}");

            var factory = GetProviderFactory(_providerName);
            var targetConnection = factory.CreateConnection();
            targetConnection.ConnectionString = _connectionString;

            var connectionId = Guid.NewGuid().ToString();
            var proxyConnection = new AtConnectionProxy(
                this,
                _transactionManager,
                _loggerFactory.CreateLogger<AtConnectionProxy>(),
                _loggerFactory,
                targetConnection,
                _dialect,
                _tableMetaCache);

            _connections.TryAdd(connectionId, proxyConnection);

            return proxyConnection;
        }

        /// <summary>
        /// 注册连接到连接池
        ///
        /// 将外部创建的AtConnectionProxy注册到数据源代理的连接池中，用于跟踪和管理连接。
        ///
        /// 执行流程：
        /// 1. 检查connection参数是否为null：
        ///    - 如果为null，抛出ArgumentNullException
        /// 2. 生成唯一的连接ID（GUID）
        /// 3. 将连接强制转换为AtConnectionProxy类型
        /// 4. 调用_connections.TryAdd()添加到连接池
        /// 5. 记录调试日志，包含connectionId
        ///
        /// 调用时机：
        /// - 外部手动创建AtConnectionProxy时需要注册
        /// - CreateConnection()方法会自动调用注册
        /// - 通常应用代码不需要直接调用此方法
        ///
        /// 注意事项：
        /// - connection必须是AtConnectionProxy类型，否则转换会失败
        /// - 使用TryAdd()确保线程安全，即使并发调用也不会出错
        /// - 连接ID是自动生成的GUID，不对外暴露
        /// - 连接关闭时应调用UnregisterConnection()注销
        /// </summary>
        /// <param name="connection">待注册的数据库连接（必须是AtConnectionProxy类型）</param>
        /// <exception cref="ArgumentNullException">connection为null时抛出</exception>
        public void RegisterConnection(DbConnection connection)
        {
            if (connection == null)
            {
                throw new ArgumentNullException(nameof(connection));
            }

            var connectionId = Guid.NewGuid().ToString();
            _connections.TryAdd(connectionId, connection as AtConnectionProxy);
            _logger.LogDebug($"注册AT连接: ConnectionId={connectionId}");
        }

        /// <summary>
        /// 从连接池中注销连接
        ///
        /// 当连接关闭或释放时，从连接池中移除该连接，停止跟踪。
        ///
        /// 执行流程：
        /// 1. 在_connections字典中查找与connection匹配的键值对：
        ///    - 使用FirstOrDefault()遍历查找
        ///    - 比较值（AtConnectionProxy对象引用）
        /// 2. 检查是否找到匹配的连接：
        ///    - 如果找不到，不执行任何操作（幂等）
        /// 3. 如果找到：
        ///    - 调用_connections.TryRemove()移除连接
        ///    - 传入找到的key进行移除
        ///
        /// 调用时机：
        /// - AtConnectionProxy.Close()或Dispose()时自动调用
        /// - 连接关闭时清理资源
        /// - 应用代码通常不需要手动调用
        ///
        /// 注意事项：
        /// - 操作是幂等的，重复注销不会出错
        /// - 使用TryRemove()确保线程安全
        /// - 注销后的连接不再被数据源代理跟踪
        /// - 如果连接从未注册，调用此方法无影响
        /// </summary>
        /// <param name="connection">待注销的数据库连接</param>
        public void UnregisterConnection(DbConnection connection)
        {
            var connectionToRemove = _connections.FirstOrDefault(kvp => kvp.Value == connection);
            if (!connectionToRemove.Equals(default(KeyValuePair<string, AtConnectionProxy>)))
            {
                _connections.TryRemove(connectionToRemove.Key, out _);
            }
        }

        /// <summary>
        /// 注册AT分支事务
        ///
        /// 在本地事务提交前，向TC注册分支事务并申请全局锁。
        ///
        /// 执行流程：
        /// 1. 记录调试日志，包含XID和ResourceId
        /// 2. 使用try-catch包裹注册逻辑：
        ///    - 调用_transactionManager.RegisterBranchAsync()
        ///    - 传入xid（全局事务ID）、resourceId（资源ID）、lockKeys（全局锁键）
        /// 3. 如果注册成功：
        ///    - TC分配branchId并注册全局锁
        ///    - 记录成功日志
        ///    - 返回true
        /// 4. 如果发生异常：
        ///    - 记录错误日志，包含异常信息
        ///    - 返回false（注册失败）
        ///
        /// 分支注册的作用：
        /// - 将本地事务关联到全局事务
        /// - 向TC申请全局锁（防止脏写）
        /// - 获取branchId用于后续操作（提交/回滚）
        /// - TC记录分支信息用于二阶段操作
        ///
        /// 全局锁（lockKeys）说明：
        /// - 格式：表名:主键值，如"account_table:1001"
        /// - 多个锁用分号分隔，如"account_table:1001;1002"
        /// - TC会检查锁冲突，冲突时注册失败
        /// - 本地事务提交后锁依然保持，直到全局事务提交
        ///
        /// 调用时机：
        /// - AtConnectionProxy.Commit()提交本地事务前
        /// - 所有业务SQL执行完毕，undo_log已生成
        /// - 在同一个数据库事务中
        ///
        /// 使用场景：
        /// ```
        /// 1. 执行业务SQL：UPDATE account SET balance=900 WHERE id=1001
        /// 2. 生成undo_log（before/after image）
        /// 3. 插入undo_log到数据库
        /// 4. 调用RegisterBranch()注册分支事务
        /// 5. 提交本地事务（释放本地锁）
        /// 6. 等待TC的二阶段指令（commit或rollback）
        /// ```
        ///
        /// 注意事项：
        /// - 注册失败应该回滚本地事务
        /// - lockKeys不能为空或null
        /// - resourceId通常是数据库连接字符串的哈希值
        /// - 返回false不会抛出异常，需要调用方处理
        /// - 注册失败可能是因为全局锁冲突或网络故障
        /// </summary>
        /// <param name="xid">全局事务ID</param>
        /// <param name="resourceId">资源ID（数据库标识）</param>
        /// <param name="lockKeys">全局锁键，格式：表名:主键值</param>
        /// <returns>注册成功返回true，失败返回false</returns>
        public async Task<bool> RegisterBranch(string xid, string resourceId, string lockKeys)
        {
            _logger.LogDebug($"注册AT分支事务: XID={xid}, ResourceId={resourceId}");

            try
            {
                // 注册分支事务
                await _transactionManager.RegisterBranchAsync(xid, resourceId, lockKeys);

                _logger.LogDebug($"AT分支事务注册成功: XID={xid}");
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"注册AT分支事务异常: XID={xid}");
                return false;
            }
        }

        /// <summary>
        /// 上报AT分支事务状态
        ///
        /// 向TC报告分支事务的执行状态（成功或失败）。
        ///
        /// 执行流程：
        /// 1. 记录调试日志，包含XID、BranchId和Status
        /// 2. 使用try-catch包裹上报逻辑：
        ///    - 调用_transactionManager.ReportStatusAsync()
        ///    - 传入xid（全局事务ID）、branchId（分支ID）、status（分支状态）
        /// 3. 如果上报成功：
        ///    - 记录成功日志
        ///    - 返回true
        /// 4. 如果发生异常：
        ///    - 记录错误日志，包含异常信息
        ///    - 返回false（上报失败）
        ///
        /// 分支状态（BranchStatus）说明：
        /// - PhaseOne_Done：一阶段完成（本地事务提交成功）
        /// - PhaseOne_Failed：一阶段失败（本地事务提交失败）
        /// - PhaseTwo_Committed：二阶段提交完成
        /// - PhaseTwo_CommitFailed_Retryable：二阶段提交失败（可重试）
        /// - PhaseTwo_Rollbacked：二阶段回滚完成
        /// - PhaseTwo_RollbackFailed_Retryable：二阶段回滚失败（可重试）
        ///
        /// 调用时机：
        /// - 一阶段完成：本地事务提交后上报PhaseOne_Done
        /// - 一阶段失败：本地事务回滚后上报PhaseOne_Failed
        /// - 二阶段提交：删除undo_log后上报PhaseTwo_Committed
        /// - 二阶段回滚：执行回滚后上报PhaseTwo_Rollbacked
        ///
        /// 上报的作用：
        /// - TC根据状态决定后续操作
        /// - 记录分支执行历史
        /// - 用于异常恢复和重试
        ///
        /// 注意事项：
        /// - 上报失败不影响本地事务结果
        /// - TC会定期检查分支状态（超时机制）
        /// - 返回false不会抛出异常，需要调用方处理
        /// - 建议实现重试机制（上报失败时）
        /// </summary>
        /// <param name="xid">全局事务ID</param>
        /// <param name="branchId">分支事务ID</param>
        /// <param name="status">分支事务状态</param>
        /// <returns>上报成功返回true，失败返回false</returns>
        public async Task<bool> ReportBranchStatus(string xid, long branchId, BranchStatus status)
        {
            _logger.LogDebug($"上报AT分支事务状态: XID={xid}, BranchId={branchId}, Status={status}");

            try
            {
                // 发送状态上报请求
                await _transactionManager.ReportStatusAsync(xid, branchId, status);

                _logger.LogDebug($"AT分支事务状态上报成功: XID={xid}, BranchId={branchId}");
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"上报AT分支事务状态异常: XID={xid}, BranchId={branchId}");
                return false;
            }
        }

        /// <summary>
        /// 执行AT回滚操作
        ///
        /// 在TC发起二阶段回滚时，查询undo_log并执行反向SQL恢复数据。
        ///
        /// 执行流程：
        /// 1. 记录调试日志，包含XID和BranchId
        /// 2. 使用try-catch包裹回滚逻辑
        /// 3. 调用QueryUndoLogs()查询undo_log记录：
        ///    - 根据xid和branchId查询
        ///    - 返回该分支的所有undo_log
        /// 4. 检查查询结果：
        ///    - 如果undoLogs为空，记录警告日志并返回true（可能已提交删除）
        /// 5. 按相反顺序执行回滚（从最后一条开始）：
        ///    - 倒序遍历undoLogs列表（for循环从后往前）
        ///    - 对每条undo_log调用ExecuteUndo()
        ///    - 根据SQL类型生成反向SQL并执行：
        ///      - INSERT → DELETE
        ///      - UPDATE → UPDATE（恢复到before image）
        ///      - DELETE → INSERT
        /// 6. 如果任何一条回滚失败：
        ///    - 记录错误日志
        ///    - 返回false（回滚失败）
        /// 7. 所有回滚成功后：
        ///    - 调用DeleteUndoLogs()删除undo_log记录
        ///    - 记录成功日志
        ///    - 返回true
        /// 8. 如果发生异常：
        ///    - 记录错误日志，包含异常信息
        ///    - 返回false
        ///
        /// 为什么倒序回滚：
        /// - 保证数据一致性：最后执行的操作最先回滚
        /// - 例如：先INSERT后UPDATE，回滚时先撤销UPDATE，再撤销INSERT
        /// - 避免外键约束和依赖关系问题
        ///
        /// 调用时机：
        /// - TC发送BranchRollbackRequest
        /// - BranchRollback处理器调用此方法
        /// - 全局事务需要回滚时
        ///
        /// 回滚示例：
        /// ```
        /// 原始操作：
        /// 1. INSERT INTO account (id, balance) VALUES (1001, 1000)
        /// 2. UPDATE account SET balance = 900 WHERE id = 1001
        ///
        /// 回滚操作（倒序）：
        /// 1. UPDATE account SET balance = 1000 WHERE id = 1001  （撤销第2步）
        /// 2. DELETE FROM account WHERE id = 1001                 （撤销第1步）
        /// ```
        ///
        /// 注意事项：
        /// - 回滚操作应该在数据库事务中执行（保证原子性）
        /// - 如果undo_log找不到，视为已提交（返回true）
        /// - 回滚失败可能需要人工介入
        /// - 返回false不会抛出异常，TC会重试
        /// - 删除undo_log是最后一步，确保回滚可重复执行
        /// </summary>
        /// <param name="xid">全局事务ID</param>
        /// <param name="branchId">分支事务ID</param>
        /// <returns>回滚成功返回true，失败返回false</returns>
        public async Task<bool> Undo(string xid, long branchId)
        {
            _logger.LogDebug($"执行AT回滚: XID={xid}, BranchId={branchId}");

            try
            {
                // 查询回滚日志
                var undoLogs = await QueryUndoLogs(xid, branchId);

                if (undoLogs == null || undoLogs.Count == 0)
                {
                    _logger.LogWarning($"未找到回滚日志: XID={xid}, BranchId={branchId}");
                    return true;
                }

                // 按照相反的顺序执行回滚
                for (int i = undoLogs.Count - 1; i >= 0; i--)
                {
                    var undoLog = undoLogs[i];

                    if (!await ExecuteUndo(undoLog))
                    {
                        _logger.LogError($"执行回滚失败: XID={xid}, BranchId={branchId}, Table={undoLog.TableName}");
                        return false;
                    }
                }

                // 删除回滚日志
                await DeleteUndoLogs(xid, branchId);

                _logger.LogDebug($"AT回滚执行成功: XID={xid}, BranchId={branchId}");
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"执行AT回滚异常: XID={xid}, BranchId={branchId}");
                return false;
            }
        }

        /// <summary>
        /// 注册数据库提供程序工厂
        ///
        /// 使用反射动态注册所有支持的数据库提供程序工厂。
        ///
        /// 执行流程：
        /// 1. 注册SQL Server提供程序：
        ///    - 首先尝试加载Microsoft.Data.SqlClient（推荐）
        ///    - 如果失败，回退到System.Data.SqlClient（兼容）
        ///    - 使用反射获取SqlClientFactory.Instance静态属性
        ///    - 添加到_providerFactories字典
        /// 2. 注册MySQL提供程序：
        ///    - 尝试加载MySql.Data.MySqlClient.MySqlClientFactory
        ///    - 使用反射获取Instance属性
        ///    - 添加到_providerFactories字典
        /// 3. 注册PostgreSQL提供程序：
        ///    - 尝试加载Npgsql.NpgsqlFactory
        ///    - 使用反射获取Instance属性
        ///    - 添加到_providerFactories字典
        /// 4. 注册SQLite提供程序：
        ///    - 尝试加载Microsoft.Data.Sqlite.SqliteFactory
        ///    - 使用反射获取Instance属性
        ///    - 添加到_providerFactories字典
        /// 5. 每个注册失败的提供程序：
        ///    - 捕获异常（通常是TypeLoadException）
        ///    - 记录警告日志，提示提供程序不可用
        ///
        /// 反射加载步骤：
        /// 1. Type.GetType("FullTypeName, AssemblyName")加载类型
        /// 2. GetProperty("Instance", BindingFlags.Public | BindingFlags.Static)获取静态属性
        /// 3. GetValue(null)获取属性值（null因为是静态属性）
        /// 4. 强制转换为DbProviderFactory
        ///
        /// 为什么使用反射：
        /// - 避免硬依赖：不需要引用所有数据库提供程序的NuGet包
        /// - 动态加载：运行时根据可用的程序集加载
        /// - 灵活性：用户只需安装需要的数据库提供程序
        ///
        /// 支持的提供程序版本：
        /// - SQL Server：Microsoft.Data.SqlClient 2.0+（推荐）/ System.Data.SqlClient 4.0+
        /// - MySQL：MySql.Data 8.0+
        /// - PostgreSQL：Npgsql 4.0+
        /// - SQLite：Microsoft.Data.Sqlite 3.0+
        ///
        /// 注意事项：
        /// - 构造函数中自动调用，无需手动调用
        /// - 注册失败不影响其他提供程序
        /// - 至少需要注册一个提供程序才能正常工作
        /// - 如果使用的提供程序未注册，CreateConnection()会抛出异常
        /// - 提供程序的NuGet包必须在运行时可用
        /// </summary>
        private void RegisterProviderFactories()
        {
            // 注册SQL Server提供程序
            try
            {
                // 尝试使用Microsoft.Data.SqlClient (新版本)
                var sqlClientType = Type.GetType("Microsoft.Data.SqlClient.SqlClientFactory, Microsoft.Data.SqlClient");
                if (sqlClientType != null)
                {
                    var factoryProperty = sqlClientType.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static);
                    if (factoryProperty != null)
                    {
                        _providerFactories["Microsoft.Data.SqlClient"] = (DbProviderFactory)factoryProperty.GetValue(null);
                    }
                }
                else
                {
                    // 回退到System.Data.SqlClient (旧版本)
                    var legacySqlType = Type.GetType("System.Data.SqlClient.SqlClientFactory, System.Data");
                    if (legacySqlType != null)
                    {
                        var factoryProperty = legacySqlType.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static);
                        if (factoryProperty != null)
                        {
                            _providerFactories["System.Data.SqlClient"] = (DbProviderFactory)factoryProperty.GetValue(null);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "SQL Server provider not available");
            }

            // 注册MySQL提供程序
            try
            {
                var mysqlType = Type.GetType("MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data");
                if (mysqlType != null)
                {
                    var instance = mysqlType.GetProperty("Instance")?.GetValue(null) as DbProviderFactory;
                    if (instance != null)
                    {
                        _providerFactories["MySql.Data.MySqlClient"] = instance;
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "MySQL provider not available");
            }

            // 注册PostgreSQL提供程序
            try
            {
                var npgsqlType = Type.GetType("Npgsql.NpgsqlFactory, Npgsql");
                if (npgsqlType != null)
                {
                    var instance = npgsqlType.GetProperty("Instance")?.GetValue(null) as DbProviderFactory;
                    if (instance != null)
                    {
                        _providerFactories["Npgsql"] = instance;
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "PostgreSQL provider not available");
            }

            // 注册SQLite提供程序
            try
            {
                var sqliteType = Type.GetType("Microsoft.Data.Sqlite.SqliteFactory, Microsoft.Data.Sqlite");
                if (sqliteType != null)
                {
                    var instance = sqliteType.GetProperty("Instance")?.GetValue(null) as DbProviderFactory;
                    if (instance != null)
                    {
                        _providerFactories["Microsoft.Data.Sqlite"] = instance;
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "SQLite provider not available");
            }
        }

        /// <summary>
        /// 获取数据库提供程序工厂
        ///
        /// 根据提供程序名称从注册的工厂字典中获取对应的DbProviderFactory。
        ///
        /// 执行流程：
        /// 1. 调用_providerFactories.TryGetValue()查找工厂：
        ///    - 传入providerName作为键
        ///    - 使用out参数factory接收结果
        /// 2. 如果找到：
        ///    - 返回DbProviderFactory实例
        /// 3. 如果找不到：
        ///    - 抛出NotSupportedException异常
        ///    - 异常消息包含不支持的提供程序名称
        ///
        /// 调用时机：
        /// - CreateConnection()创建连接时调用
        /// - 获取工厂用于创建DbConnection对象
        ///
        /// 常见提供程序名称：
        /// - "Microsoft.Data.SqlClient"：SQL Server（推荐）
        /// - "System.Data.SqlClient"：SQL Server（旧版本）
        /// - "MySql.Data.MySqlClient"：MySQL
        /// - "Npgsql"：PostgreSQL
        /// - "Microsoft.Data.Sqlite"：SQLite
        ///
        /// 注意事项：
        /// - providerName必须与RegisterProviderFactories()注册的名称完全匹配
        /// - 大小写敏感
        /// - 如果提供程序未注册或注册失败，会抛出异常
        /// - 建议在构造函数中检查必需的提供程序是否可用
        /// </summary>
        /// <param name="providerName">数据库提供程序名称</param>
        /// <returns>DbProviderFactory实例</returns>
        /// <exception cref="NotSupportedException">提供程序未注册时抛出</exception>
        private DbProviderFactory GetProviderFactory(string providerName)
        {
            if (_providerFactories.TryGetValue(providerName, out var factory))
            {
                return factory;
            }

            throw new NotSupportedException($"不支持的数据库提供程序: {providerName}");
        }

        /// <summary>
        /// 查询UndoLog记录
        ///
        /// 从undo_log表中查询指定全局事务和分支的回滚日志。
        ///
        /// 执行流程：
        /// 1. 记录调试日志，包含XID和BranchId
        /// 2. 创建数据库连接并打开
        /// 3. 查询undo_log表：
        ///    - SELECT * FROM undo_log WHERE xid = ? AND branch_id = ?
        ///    - ORDER BY log_created ASC（按创建时间升序）
        /// 4. 遍历查询结果：
        ///    - 读取rollback_info字段（JSON格式）
        ///    - 反序列化为AtUndoLog对象
        ///    - 添加到结果列表
        /// 5. 返回AtUndoLog列表
        ///
        /// 注意事项：
        /// - 当前实现返回空列表（示例代码）
        /// - 实际实现需要：
        ///   - 使用IUndoLogManager.QueryUndoLogAsync()查询
        ///   - 使用IUndoLogParser.Parse()反序列化
        ///   - 正确处理数据库连接和事务
        /// - 查询操作可以使用独立的连接（不需要在事务中）
        /// - 如果找不到记录，返回空列表（不抛出异常）
        /// </summary>
        /// <param name="xid">全局事务ID</param>
        /// <param name="branchId">分支事务ID</param>
        /// <returns>UndoLog记录列表，可能为空</returns>
        private async Task<List<AtUndoLog>> QueryUndoLogs(string xid, long branchId)
        {
            // 这里应该从undo_log表中查询回滚日志
            // 在实际实现中，需要创建数据库连接并执行查询

            _logger.LogDebug($"查询回滚日志: XID={xid}, BranchId={branchId}");

            // 示例代码，返回空列表
            return new List<AtUndoLog>();
        }

        /// <summary>
        /// 执行单条UndoLog的回滚
        ///
        /// 根据undo_log记录生成反向SQL并执行，恢复数据到事务前的状态。
        ///
        /// 执行流程：
        /// 1. 记录调试日志，包含表名和XID
        /// 2. 创建数据库连接并开启事务
        /// 3. 根据SQL类型生成反向SQL：
        ///    - INSERT → DELETE（使用AfterImage的主键）
        ///    - UPDATE → UPDATE（使用BeforeImage恢复数据）
        ///    - DELETE → INSERT（使用BeforeImage重新插入）
        /// 4. 执行反向SQL：
        ///    - 使用参数化查询
        ///    - 在事务中执行
        /// 5. 提交事务
        /// 6. 返回true（成功）
        ///
        /// 注意事项：
        /// - 当前实现返回true（示例代码）
        /// - 实际实现需要：
        ///   - 使用IUndoLogExecutor.ExecuteRollbackAsync()
        ///   - 正确处理数据库连接和事务
        ///   - 实现脏写检测（对比AfterImage和当前数据）
        /// - 执行失败应该抛出异常或返回false
        /// - 回滚操作应该是幂等的（可重复执行）
        /// </summary>
        /// <param name="undoLog">UndoLog记录，包含回滚所需信息</param>
        /// <returns>执行成功返回true，失败返回false</returns>
        private async Task<bool> ExecuteUndo(AtUndoLog undoLog)
        {
            // 这里应该根据回滚日志执行回滚操作
            // 在实际实现中，需要创建数据库连接并执行回滚SQL

            _logger.LogDebug($"执行回滚操作: Table={undoLog.TableName}, XID={undoLog.Xid}");

            // 示例代码，返回true
            return true;
        }

        /// <summary>
        /// 删除UndoLog记录
        ///
        /// 从undo_log表中删除指定全局事务和分支的回滚日志。
        ///
        /// 执行流程：
        /// 1. 记录调试日志，包含XID和BranchId
        /// 2. 创建数据库连接并打开
        /// 3. 执行DELETE SQL：
        ///    - DELETE FROM undo_log WHERE xid = ? AND branch_id = ?
        /// 4. 返回true（成功）
        ///
        /// 调用时机：
        /// - 回滚操作完成后删除undo_log
        /// - 二阶段提交时删除undo_log
        /// - 确保回滚日志不再需要
        ///
        /// 注意事项：
        /// - 当前实现返回true（示例代码）
        /// - 实际实现需要：
        ///   - 使用IUndoLogManager.DeleteUndoLogAsync()删除
        ///   - 正确处理数据库连接
        ///   - 可以在独立的连接中执行（不需要事务）
        /// - 删除操作是幂等的（重复删除不报错）
        /// - 如果记录不存在，不应该抛出异常
        /// </summary>
        /// <param name="xid">全局事务ID</param>
        /// <param name="branchId">分支事务ID</param>
        /// <returns>删除成功返回true，失败返回false</returns>
        private async Task<bool> DeleteUndoLogs(string xid, long branchId)
        {
            // 这里应该从undo_log表中删除回滚日志
            // 在实际实现中，需要创建数据库连接并执行删除

            _logger.LogDebug($"删除回滚日志: XID={xid}, BranchId={branchId}");

            // 示例代码，返回true
            return true;
        }
    }
}